#include "DialogChatServer.h"

#define  MSGSHOW_WIDTH  300

// 设置窗口单例对象
gChatServer &gChatServer::Instance()
{
    static gChatServer m_gChatServer;
    return m_gChatServer;
}

// 初始化界面
void gChatServer::init()
{
    // 注册节点更新结构体到信号中使用
    qRegisterMetaType<QList<NODE_INFO>>("QList<NODE_INFO>");

    m_bMsgBrowserStatus = false;
    m_bExit = false;
    // 去掉窗口的问号
    Qt::WindowFlags flags = Qt::Dialog;
    flags |= Qt::WindowCloseButtonHint;
    setWindowFlags(flags);

    // 设定提示框主图标
    setWindowIcon(QIcon(":/operationIcons/resource/operationIcons/fish_forest.ico"));
    setWindowTitle(QStringLiteral("鱼塘服务端"));
    setFont(gstFont);

    QHBoxLayout *pLayoutMain = new QHBoxLayout;
    setLayout(pLayoutMain);

    QVBoxLayout *pLayoutInfo = new QVBoxLayout;     // 创建左侧设置信息栏
    m_pBoxMySetInfo = new QGroupBox(this);          // 创建个人信息设置栏
    m_pBoxOperation = new QGroupBox(this);          // 创建操作栏
    m_pBoxFriendsInfo = new QGroupBox(this);        // 创建群友信息栏
    pLayoutInfo->addWidget(m_pBoxMySetInfo);
    pLayoutInfo->addWidget(m_pBoxOperation);
    pLayoutInfo->addWidget(m_pBoxFriendsInfo);
    pLayoutMain->addLayout(pLayoutInfo);

    m_pMsgBrowser = new QTextBrowser(this);       // 创建消息展示框
    pLayoutMain->addWidget(m_pMsgBrowser);
    m_pMsgBrowser->hide();
    m_pMsgBrowser->setMinimumWidth(MSGSHOW_WIDTH);

    // 生成控件界面
    newToolFunc();

    // 设置默认操作状态
    setDefault();

    m_iDialogWidth = this->width();

    // 连接本对象信号，用于消息线程异步消息展示
    connect(this, SIGNAL(sengMsg2Show(QString, QString)), this, SLOT(slt_ShowMsgInfo(QString, QString)));
    // 刷新好友列表
    connect(this, SIGNAL(sendListNodeStatus(QList<NODE_INFO>)), this, SLOT(stl_UpdateNodeStatus(QList<NODE_INFO>)));

    // 初始化网络模块
    if(false == TcpGlobalInit())
    {
        qDebug() << "[gChatServer] Network module Global Init FAILD!";
        return;
    }
}

// 生成控件界面
void gChatServer::newToolFunc()
{
    uint ilenShowInfo = 280;
    m_pBoxMySetInfo->setMaximumWidth(ilenShowInfo);
    m_pBoxOperation->setMaximumWidth(ilenShowInfo);
    m_pBoxFriendsInfo->setMaximumWidth(ilenShowInfo);
    m_pBoxFriendsInfo->setMinimumHeight(200);

    m_pBoxMySetInfo->setTitle(QStringLiteral("我的鱼情"));
    m_pBoxOperation->setTitle(QStringLiteral("鱼塘操作"));
    m_pBoxFriendsInfo->setTitle(QStringLiteral("鱼塘鱼情"));
    m_pBoxMySetInfo->setFont(gstFont);
    m_pBoxOperation->setFont(gstFont);
    m_pBoxFriendsInfo->setFont(gstFont);

    QVBoxLayout *pLayoutInfo = new QVBoxLayout;
    m_pBoxMySetInfo->setLayout(pLayoutInfo);
    QFormLayout *pFormLayoutMyInfo = new QFormLayout;
    pLayoutInfo->addLayout(pFormLayoutMyInfo);

    m_pServerIP = new QLineEdit(this);
    m_pServerPort = new QLineEdit(this);
    m_pServerKey = new QLineEdit(this);
    m_pServerNumber = new QLineEdit(this);
    m_pServerIP->setAlignment( Qt::AlignHCenter);
    m_pServerPort->setAlignment( Qt::AlignHCenter);
    m_pServerKey->setAlignment( Qt::AlignHCenter);
    m_pServerNumber->setAlignment( Qt::AlignHCenter);

    m_pServerPort->setPlaceholderText(QStringLiteral("数字"));
    m_pServerKey->setPlaceholderText(QStringLiteral("英文字母和数字"));
    m_pServerNumber->setPlaceholderText(QStringLiteral("数字"));
    QString strMyIP = getMyIpString();
    m_pServerIP->setText(strMyIP);
    m_pServerIP->setEnabled(false);

    pFormLayoutMyInfo->addRow(QStringLiteral("本机地址"), m_pServerIP);
    pFormLayoutMyInfo->addRow(QStringLiteral("群组端口"), m_pServerPort);
    pFormLayoutMyInfo->addRow(QStringLiteral("群组口令"), m_pServerKey);
    pFormLayoutMyInfo->addRow(QStringLiteral("群员限额"), m_pServerNumber);

    QGridLayout *pLayoutAction = new QGridLayout;
    QPushButton *pStartServer = NewPTBWithIcon(QStringLiteral("启用"), QStringLiteral("开启聊天室服务"), QIcon(QString(":/operationIcons/resource/operationIcons/fish_forest.ico")), this);
    QPushButton *pStopServer = NewPTBWithIcon(QStringLiteral("停止"), QStringLiteral("停止聊天室服务"), QIcon(QString(":/operationIcons/resource/operationIcons/information_warn.ico")), this);
    QPushButton *pShowMsg = NewPTBWithIcon(QStringLiteral("查看后台 >>"), QStringLiteral("查看后台聊天记录"), QIcon(QString(":/operationIcons/resource/operationIcons/information_succeed.ico")), this);
    connect(pStartServer, SIGNAL(clicked()), this, SLOT(slt_StartServer()));
    connect(pStopServer, SIGNAL(clicked()), this, SLOT(slt_StopServer()));
    connect(pShowMsg, SIGNAL(clicked()), this, SLOT(slt_ShowChatMsg()));
    pLayoutAction->addWidget(pStartServer, 0, 0);
    pLayoutAction->addWidget(pStopServer, 0, 1);
    pLayoutAction->addWidget(pShowMsg, 0, 2);
    m_pBoxOperation->setLayout(pLayoutAction);

    QHBoxLayout *pLayoutFriends = new QHBoxLayout;
    QTextBrowser *pFriends = new QTextBrowser(this);
    pLayoutFriends->addWidget(pFriends);
    m_pBoxFriendsInfo->setLayout(pLayoutFriends);
}

// 主控件设置默认配置
void gChatServer::setDefault()
{
    m_pBoxMySetInfo->adjustSize();
    m_pMsgBrowser->adjustSize();
}

// 释放资源
void gChatServer::release()
{
    m_bExit = true;
    if(nullptr != m_pNodeServer)
    {
        m_pNodeServer->setCallBackExit();
    }
    
    if(m_thCallBackMsg.joinable())
    {
        m_thCallBackMsg.join();
    }

    if(nullptr != m_pNodeServer)
    {
        delete m_pNodeServer;
        m_pNodeServer = nullptr;
    }
}

// 启动服务
void gChatServer::slt_StartServer()
{
    // 重新
    if(nullptr == m_pNodeServer)
    {
        m_pNodeServer = new nodeServer;
        if(nullptr == m_pNodeServer)
        {
            qDebug() << "[gChatServer] NodeServer create FAILD!";
            return;
        }

        // 设置网络模块交互消息展示到上层
        m_pNodeServer->setCallBackStatus(true);

        try
        {
            m_thCallBackMsg = std::thread(&gChatServer::threadCallBackMsg, this);
        }
        catch(const std::exception& e)
        {
            qDebug() << "[gChatServer] thread create FAILD!" << QString::fromStdString(e.what());
            return;
        }
    }

    std::string strNodeKey = "test123";
    unsigned int uiPort = 2656;
    unsigned int uiListenSize = 10;
    if(false == m_pNodeServer->init(strNodeKey, uiPort, uiListenSize))
    {
        qDebug() << "[gChatServer] NodeServer init FAILD!";
    }
}

// 取消服务
void gChatServer::slt_StopServer()
{
    
}

// 查看后台聊天内容
void gChatServer::slt_ShowChatMsg()
{
    m_bMsgBrowserStatus = !m_bMsgBrowserStatus;
    uint iWidth = m_iDialogWidth;
    uint iHeight = this->height();
    if(true == m_bMsgBrowserStatus)
    {
        m_pMsgBrowser->show();
    }
    else
    {
        m_pMsgBrowser->hide();
        iWidth = m_iDialogWidth - MSGSHOW_WIDTH - 40;
    }
    
    setFixedSize(iWidth, iHeight);
}

// 展示数据
void gChatServer::slt_ShowMsgInfo(QString strInfo, QString strMsg)
{
    m_pMsgBrowser->insertHtml(strInfo);
    m_pMsgBrowser->insertHtml(strMsg);
}

// 更新节点状态
void gChatServer::stl_UpdateNodeStatus(QList<NODE_INFO> listNodeStatus)
{
    if(listNodeStatus.empty())
    {
        return;
    }

    for(auto it : listNodeStatus)
    {
        qDebug() << "gChatServer::stl_UpdateNodeStatus " << it.nType << it.strNodeID;
    }
}

// 从网络模块中获取交互消息用于上层展示
void gChatServer::threadCallBackMsg()
{
    if(nullptr == m_pNodeServer)
    {
        qDebug() << "[gChatServer] thread proc : NodeServer create FAILD!, return";
        return;
    }

    qDebug() << "[gChatServer] threadCallBackMsg working ... ";
    while (!m_bExit)
    {
        std::list<MSG_INFO> listMsgInfo;

        if(nullptr != m_pNodeServer)
        {
            m_pNodeServer->getCallBackMsgWithCondition(listMsgInfo);
        }
        else
        {
            qDebug() << "[gChatServer] threadCallBackMsg m_pNodeServer is null";
        }
        
        if(m_bExit)
        {
            break;
        }

        // 展示数据
        QList<NODE_INFO> listNodeStatus;
        listNodeStatus.clear();
        for(auto it : listMsgInfo)
        {
            // 收集节点状态的消息，并通知列表更新
            if( MSG_INFO_TYPE_STATUS_NEW == it.nType || MSG_INFO_TYPE_STATUS_OFF == it.nType || MSG_INFO_TYPE_STATUS_EXIT == it.nType)
            {
                NODE_INFO stNodeStatus;
                stNodeStatus.nType = it.nType;
                stNodeStatus.strNodeID = QString::fromStdString(it.strID);
                listNodeStatus.push_back(stNodeStatus);
            }

            QString strInfo, strShowMsg;
            getBrowserShowInfo(it, strInfo, strShowMsg);
            // 不能直接由线程操作控件，需通过信号方式触发
            emit sengMsg2Show(strInfo, strShowMsg);
        }

        // 更新群友列表
        if(!listNodeStatus.empty())
        {
            emit sendListNodeStatus(listNodeStatus);
        }
    }
}
